package com.shopManager.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class RedisLockUtils {

	private static final Logger LOGGER = LoggerFactory.getLogger(RedisLockUtils.class);
	public static final String REDIS_LOCK = "RedisLock:";

	private static final long DEFAULT_WAIT_LOCK_TIME_OUT = 60;// 60s 有慢sql，超时时间设置长一点
	private static final long DEFAULT_EXPIRE = 80;// 80s 有慢sql，超时时间设置长一点
	private String key;
	@Autowired
	private RedisTemplate redisTemplate;

	/**
	 * 等待锁的时间,单位为s
	 *
	 * @param key
	 * @param timeout s
	 * @param seconds
	 */
	public boolean lock(String key, long timeout, TimeUnit seconds,String value) {
		long nanoWaitForLock = seconds.toNanos(timeout);
		long start = System.nanoTime();
		RedisConnection connection =redisTemplate.getConnectionFactory().getConnection();
		try {
			LOGGER.debug("开始获取锁"+key+"value:"+value);
			while ((System.nanoTime() - start) < nanoWaitForLock) {
				if (connection.setNX(key.getBytes(), value.getBytes()) ) {
					redisTemplate.expire(key, DEFAULT_EXPIRE, TimeUnit.SECONDS);// 暂设置为80s过期，防止异常中断锁未释放
					if (LOGGER.isDebugEnabled()) {
						LOGGER.debug("add RedisLock["+key+"]."+ Thread.currentThread());
					}
					return true;
				}
				TimeUnit.MILLISECONDS.sleep(1000 + new Random().nextInt(100));// 加随机时间防止活锁
			}
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
			unlock(key,value);
		}finally
		{
			connection.close();
		}
		return false;
	}

	public void unlock(String key,String value) {
		try {
			Object object = redisTemplate.opsForValue().get(key);
			
			if(!value.equals(object)) {
				return ;
			}
			redisTemplate.delete(key);
			
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}finally {
		}
	}

}
